<?php

class getDataHigecoTask extends baseWemTask
{
    
    private $localDir;
    private $localTmpDir;
    private $url;
    private $schema;
    private $host;
    private $remoteDir;
    private $samplingTime;
    private $pass;
    private $port;
    private $query;
    private $module;
    private $objReader;
    private $filename;
    
    //each key must be unique
    static public $samHigeco_Var = array(
        "Energy Meter"=>array("ActExpEn"=>array("Energia Attiva ceduta (2.8.0) [kWh]", "Energia attiva A- (2.8.0) [KWh]") ,
                              "ActImpEn"=>array("Energia Attiva prelevata (1.8.0) [kWh]", "Energia attiva A+ (1.8.0) [KWh]"),
                              "Pac"=>array("Power [kW]","Potenza attiva ceduta (2.7) [kW]"),                                         
                              "Cosphi"=>"Cosfi medio (13.7.0)"),
        "Weather"=>array("Irr"=>array("Irr [W/mq]","Irraggiamento [W/mq]","Irraggiamento [W/m^2]", "Irr [W/m^2]"),
                         "Tmod"=>array("Tmod [°C]","T Modulo [°C]", "Temperatura [°C]"),
                         "Tenv"=>array("Temp [°C]", "Tamb_Ext [°C]",),
                         "Tcab"=>array("Tamb_Int [°C]",),
                         "Hum"=>array("Humidity [%]",),   
                         "windSpeed"=>"Wind [m/s]",),
        "Inverter"=>array("Vac"=>array("Vac [V]","Grid Voltage dsp1 [V]","" ),
                          "Iac"=>array("Iac [A]","Grid Current dsp2 [A]"),
                          "Vac12"=>"Vac1 [V]",
                          "Vac23"=>"Vac2 [V]",
                          "Vac13"=>"Vac3 [V]",
                          "Iac1"=>"Iac1 [A]",
                          "Iac2"=>"Iac2 [A]",
                          "Iac3"=>"Iac3 [A]",
                          "Vdc1"=>array("Vdc1 [V]","Vdc [V]","Input1 Voltage dsp23 [V]",),
                          "Vdc2"=>"Vdc2 [V]",
                          "Vdc3"=>"Vdc3 [V]",
                          "Idc1"=>array("Idc1 [A]","Idc [A]","Input1 Current dsp25 [A]"),
                          "Idc2"=>"Idc2 [A]",
                          "Idc3"=>"Idc3 [A]",
                          "F"=>array("Frequenza (Hz)","Frequency (Hz)", "Frequency [Hz]"),
                          "ProdEn"=>array("Total Energy [kWh]","Total Energy ce5 [kWh]"),
                          "Pac"=>array("Power [kW]","Grid Power dsp3 [kW]"),
                          "State"=>array("State1","AlarmState stat4"),),
        "String Comb"=>array("Idc"=>array("Idc [A]","Total instant currents","Total instant currents [A]","Global Current [A]"), 
                             "Vdc"=>array("Vdc [V]","Tensione [V]","Global Parallel Voltage [V]"), 
                            "Idc1"=>array("I1 [A]","Current string 1 [A]", "Current 0 [A]"),
                            "Idc2"=>array("I2 [A]","Current string 2 [A]", "Current 1 [A]"),
                            "Idc3"=>array("I3 [A]","Current string 3 [A]", "Current 2 [A]"),
                            "Idc4"=>array("I4 [A]","Current string 4 [A]", "Current 3 [A]"),
                            "Idc5"=>array("I5 [A]","Current string 5 [A]", "Current 4 [A]"),
                            "Idc6"=>array("I6 [A]","Current string 6 [A]", "Current 5 [A]"),
                            "Idc7"=>array("I7 [A]","Current string 7 [A]", "Current 6 [A]"),
                            "Idc8"=>array("I8 [A]","Current string 8 [A]", "Current 7 [A]"),
                            "Idc9"=>array("I9 [A]","Current string 9 [A]", "Current 8 [A]"),
                            "Idc10"=>array("I10 [A]","Current string 10 [A]", "Current 9 [A]"),
                            "Idc11"=>array("I11 [A]","Current string 11 [A]"),  
                            "Idc12"=>array("I12 [A]","Current string 12 [A]"),
                            "Idc13"=>array("I13 [A]","Current string 13 [A]"),
                            "Idc14"=>array("I14 [A]","Current string 14 [A]"),
                            "Idc15"=>array("I15 [A]","Current string 15 [A]"),
                            "Idc16"=>array("I16 [A]","Current string 16 [A]"),
                            "Idc17"=>array("I17 [A]","Current string 17 [A]"),
                            "Idc18"=>array("I18 [A]","Current string 18 [A]"),
                            "State1"=>array("Fuse status","Fuse state","Fuse status [ ]"),
                            "State2"=>array("String status","String status [ ]")),
        "MV Protection"=>array("State"=>array("Stato interruttore 0-Aperto 1-Chiuso","Stato interruttore 0-Chiuso 1-Aperto","Stato interruttore"),
                               "Vac"=>"Vac [V]",
                               "Vac12"=>array("UL1 [V]","Vac1 [V]"),
                               "Vac23"=>array("UL2 [V]","Vac2 [V]"),
                               "Vac13"=>array("UL3 [V]","Vac3 [V]"),
                               "Iac"=>"Iac [A]",
                               "Iac1"=>array("Iac1 [A]","IL1 [In]"),
                               "Iac2"=>array("Iac2 [A]","IL2 [In]"),
                               "Iac3"=>array("Iac3 [A]","IL3 [In]"),
                               "f"=>array("Frequenza (Hz)","Frequenza [Hz]"),
                               ),
            
        );
    
    
    public function configure()
    {
        parent::configure();
        
        $this->name      = 'getData-higeco';
        $this->briefDescription = 'Get Data from the Higeco system, both from GWC and from Higeco Web Portal';
        
        $this->localDir="//192.168.0.37/om/NUOVO SERVER O&M/6_MONITORAGGIO/1_DATA/";
        $this->localTmpDir="C:/wamp/www/seth/data/tmp/";
        $this->schema="http://";
        $this->host='eq-monitoring.com';
        $this->port = "80";
        $this->remoteDir="phpScript/exeModuli.php";
        $this->pass="En3rq0$";
        $this->samplingTime=300;
        
        //ARGUMENTS
        $this->addArgument('plant',  sfCommandArgument::REQUIRED,'Plant to check');
        $this->addArgument('start',  sfCommandArgument::OPTIONAL,'The starting day [Format: Y-m-d]',0);
        $this->addArgument('days',  sfCommandArgument::OPTIONAL,'Number of days to check [the greater the range the longer the script..] ',5);
    }
    public function execute($arguments = array(), $options = array())
    {   
        //Get DB Connection
        $this->ConnectDB();
        
        //register task execution
        $tasklog=seth::regTaskStart($this->name, $arguments, $options );
        
         // load the HTTP codes
         $httpCodes = parse_ini_file(sfConfig::get('sf_config_dir')."/"."httpCode.ini");
         
        //get the requested plant
        $plant=Doctrine_Core::getTable('plant')->find($arguments['plant']);
        if (!is_object($plant)){
            $this->logBlock("The provided plant does not exist", "ERROR");
            seth::regTaskEnd($tasklog, false);
            die();
        }
       
        //register log file
        $this->addFileLogger($plant->getName());
        
        
        //create or get local dir for file store
        $this->localDir=$this->localDir."/".$plant->getName();
        if (!is_dir($this->localDir)){
            if(!isset($fs))
                $fs=new sfFilesystem();
            $fs->mkdirs($this->localDir);
        }
        $this->localDir=$this->localDir."/";
        
        
        //get and test remote url
        $this->url=$this->schema.$this->host.":".$this->port;
        $urlTest=parse_url($this->url);
        if (!(isset($urlTest['scheme']) and isset($urlTest['host']) and isset($urlTest['port'])))
        {
            $this->logBlock("The provided URL is not complete. \n You must provide both the SCHEME (Ex. ftp or http) and the HOST (Ex. 192.168.0.1 or www.google.it) and the PORT (Ex 21). \n\n Example: ftp://ftp.power-one.it:21", "ERROR");
            seth::regTaskEnd($tasklog, false);
            die();
        } 
        

        /* TIME RANGE DEFINITION */
        if ($arguments["start"]==0)
            $toDate=new DateTime();
        elseif (strtotime($arguments["start"]) == FALSE){
            $this->logBlock("Argument [start] provided is not valid. Must be a valid date","ERROR");
            seth::regTaskEnd($tasklog, false);
            die();
        }else{
            $toDate=new DateTime($arguments["start"]);
        }
        
        $toDate->setTime("23", "45", "00");
            
        if (!is_numeric($arguments["days"]) or $arguments["days"]<=0){
            $this->logBlock("Argument [days] provided is not valid. Must be a number >0","ERROR");
            seth::regTaskEnd($tasklog, false);
            die();
        }else
            $days=$arguments["days"];
        
        $rangeLimit=new DateTime($toDate->format("Y-m-d H:i:s"));
        $rangeLimit->sub(new DateInterval("P".$days."D"));
        
        $plantLastUpdate=$plant->getLastUpdate();
        if ($options['debug'])
            $this->logBlock("Plant last update ".$plantLastUpdate->format("Y-m-d H:i:s"),"INFO");
        
        if (!isset($plantLastUpdate)){
            $plantLastUpdate=new DateTime();
            $plantLastUpdate->setTimestamp(0);
        }
        
        if ($plantLastUpdate>=$rangeLimit){
            $fromDate=$plantLastUpdate;
            $fromStr="Plant last update";
        }else{
            $fromDate=$rangeLimit;
            $fromStr="User selected date";
        }
        
        if ($fromDate>$toDate){
            $this->logBlock(" Plant already updated for ".$toDate->format("d/m/Y H:i"), "INFO");
            seth::regTaskEnd($tasklog, false);
            die();
        }

        $this->logBlock("Searching data from ".$fromStr." ".$fromDate->format("Y-m-d H:i:s")." to ".$toDate->format("Y-m-d H:i:s"),"INFO");
        $this->logBlock("Sending HTTP request to ".$this->url."...","INFO");
        
        //building http request
        $this->module=$plant->getName();
        $arrayQuery=array(
            "act"=>"exportData",
            "requestName"=>$this->module,
            "from"=>$fromDate->format("d/m/Y H:i"),
            "to"=>$toDate->format("d/m/Y H:i"),
            "samplingTime"=>$this->samplingTime,
            "pass"=>$this->pass);
        
        $this->query=json_encode($arrayQuery);
        $this->query=urlencode($this->query);
        
        
        $this->url= $this->url."/".$this->remoteDir."/?query=".$this->query;
        
        if ($options['debug'])
            $this->logBlock("\n".urldecode ($this->url)." ...","INFO");
        
        //establish a new curl session
        $ch = curl_init($this->url);
        if (!$ch){
            $this->logBlock("Error creating new http curl session", "ERROR");
            seth::regTaskEnd($tasklog, false);
            die();
        }
        
        //defining curl channel options
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        //sending HTTP request
        $ts = microtime(true);
        $data = curl_exec($ch); 
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);  
        curl_close($ch); 
        
        if($httpCode>=200 && $httpCode<300){
           $this->logBlock("\nHost ".$this->host." responded: ".$httpCode." [".$httpCodes[$httpCode]."]"." in ".round((microtime(true) - $ts),2)."s. ","INFO");
        }elseif ($httpCode<100){ 
           $this->logBlock("Connection to ".$this->url." failed. Request timed out.","ERROR");
                }else{
                    $this->logBlock("Connection to ".$this->url." failed. Http BAD Info Code: ".$httpCode." [".$httpCodes[$httpCode]."]","ERROR");
                }
        
        /*Il server Higeco risponde ad una chiamata HTTP inviando una stringa di caratteri
         * con formattazione CSV relativa al periodo richiesto ed ai dispositivi 
         * configurati nel modulo di esportazione. Dallo stream viene creato
         * un file CSV che poi viene letto ed interpretato
         */        
                
        //test data looking for the string ERROR
        if (strpos($data,"\"STRERR\":\"")!==FALSE){
            $this->logBlock("\n ERROR, BAD response: \n".$data, "ERROR");
            seth::regTaskEnd($tasklog, false);
            die();
        }

         if ($options['debug'])
            $this->logBlock("Converting received data..","INFO");
         
         
//      Convert string response into multidimensional array  
        $rows=preg_split('/\R+/', trim($data)) ;
        foreach ($rows as $row){
            $cells[]=  preg_split('/;/', trim($row),-1,PREG_SPLIT_NO_EMPTY);
        }

        
        $updateFlag=false;
        if ($options['debug'])
           $this->logBlock("Mem usage is: ".(memory_get_usage()/1024)."KB","INFO");
        
        $this->logBlock("Reading received data..","INFO");
        
        if ($options['debug'])
            $this->logBlock("Received headers: \n".implode(" ; ",$cells[0]),"INFO");
        
        //get the list of the monitored devices
        $devs=$plant->getMonitoredPowerDev();
        
        
        // SYNC START ON DEVICES BASE
        $insertCount=array();
        if ($devs->count()>0){
            $updateFlag=false;
            foreach ($devs as $dev){
                
                
                if ($options['debug']){
                    $this->logBlock("Working on ".$dev->getLabel(),"INFO");
                    $this->logBlock("Mem usage is: ".(memory_get_usage()/1024)." KB","INFO");
                }
                
                //look for devices column
                //header cells are formatted as follows "Plant->Device->Variable"
                $vars=array();
                foreach ($cells[0] as $key=>$headCell){

                    if (strpos(strtoupper($headCell),  strtoupper($dev->getAddress()))!==FALSE){
                        
                        //check if the var is handled by seth
                        $higVar=substr($headCell,strrpos($headCell,"-->")+3);
                        $sethVar=$this->getSethVar($higVar, $dev->getType());
                        if ($sethVar){
                            $vars[$sethVar]=$key;
                        }else{
                             if ($options['debug'])
                                $this->logBlock("Variable ".$higVar." not managed by Seth","ERROR");
                        }
                    }
                }
                
                if (count($vars)>0){
                    
                    //Set new record
                    $class=$dev->getVarTableName();
                    
                    $devInsertCount=0;

                    foreach ($cells as $rowInd=>$row){
                        
                        if ($rowInd>0){
                            
                            $newVar= new $class();
                            $newVar->setDev($dev); 
                            $newVar->setSource("HigWeb:".$this->module); 
                            $t=new DateTime(str_replace("/","-",$row[0]));
                            $newVar->setsampleTime($t->format("Y-m-d H:i:s"));
                            $notNull=false;
                            
                            foreach ($vars as $sethVar=>$higKey){
                                if ($this->isValid($row[$higKey])){
                                    $notNull=true;
                                    $method="set".$sethVar;
                                    $newVar->$method($row[$higKey]);
                                }
                            }
                            
                            

                            if ($notNull){
                                try{
                                $newVar->save();
                   
                                if (!$updateFlag)
                                    $updateFlag=TRUE;
                                $devInsertCount++;
                                }catch(Doctrine_Exception $e){
                                   if ($options["debug"])
                                        $this->logBlock("Error inserting row ".$newVar->getSampleTime()." - ".$dev->getLabel().": ".$e->errorMessage(),"ERROR");
                                }
                            }
                            $newVar->free(true);    
                        }
                          
                    }
                    
                    if ($options['debug'])
                        $this->logBlock("Succesfully inserted ".$devInsertCount." record for ".$dev->getLabel(),"INFO");
                    
                    $cumulative=(isset($insertCount[$dev->getType()]))?$insertCount[$dev->getType()]:0;
                    $insertCount[$dev->getType()]=$cumulative+$devInsertCount;
                }else{
                    if ($options['debug'])
                        $this->logBlock("No variables found for ".$dev->getLabel(),"INFO");
                }
              
             }
        }else
          $this->logBlock("No device of ".$plant->getName()." monitored by Higeco", "INFO");
 
        if (!$updateFlag)
            $this->logBlock("No Updates available for ".$plant,"INFO");
        else{
            $this->logBlock($plant." updated: ","INFO");
            foreach ($insertCount as $type => $count)
                $this->logBlock("Inserted ".$count." records for type ".$type,"INFO");
        }
        
        seth::regTaskEnd($tasklog, TRUE);        
    }

    
    public function getSethVar($var, $type){
        
        if (!key_exists($type, self::$samHigeco_Var))
                return false;
        
        $devVars=self::$samHigeco_Var[$type];
        
        foreach ($devVars as $sethVar=>$alienVar){
            
            if (is_array($alienVar)){
                foreach ($alienVar as $alienVarEl ){
                   
                    if ($this->varCompare($alienVarEl,$var))
                        return $sethVar;   
                }
            }else{
            
                if ($this->varCompare($alienVar,$var)){
                    return $sethVar;
                } 
            }
            
        }
        return false;

    }
    
    private function varCompare($var1, $var2){
        $var1=str_replace(" ","",strtolower($var1));
        $var2=str_replace(" ","",strtolower($var2));
        
        if ($var1==$var2)
            return true;
        else 
            return false;
     
    }    
    
    
    public function isValid($val){
        
        if (strpos($val, "err") !== FALSE){
            return false;
        }
        
          if (strpos($val, "#E3") !== FALSE){
            return false;
        }
            return true;
        
    }
    
    

}




?>

